#include "CampaignSkillProxyModel.h"



#include <ItemModel.h>
#include <ItemReference.h>



namespace
{
QString SKILL_GROUP_NAME = ".Skill";
QString ATTRIBUTE_GROUP_NAME = ".Attribute";
}



CampaignSkillProxyModel::CampaignSkillProxyModel(QObject *parent) :
    AbstractCampaignItemModel(parent)
{
}



QModelIndex CampaignSkillProxyModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
    {
        return QModelIndex();
    }

    QList<ProxyIndex> proxies;

    if (!parent.isValid())
    {
        proxies = m_skills.proxies();
    }
    else if (m_subSkills.contains(parent))
    {
        proxies = m_subSkills.value(parent).proxies();
    }
    else
    {
        return QModelIndex();
    }


    foreach (const QModelIndex proxy, proxies)
    {
        if (!proxy.isValid()) continue;
        if (proxy.row() != row || proxy.column() != column) continue;

        return proxy;
    }

    return QModelIndex();
}



QModelIndex CampaignSkillProxyModel::parent(const QModelIndex &child) const
{
    if (!child.isValid()) return QModelIndex();

    if (m_skills.hasProxy(child)) return QModelIndex();

    QList<ProxyIndex> parents = m_subSkills.keys();
    foreach (ProxyIndex parent, parents)
    {
        IndexMap children = m_subSkills.value(parent);
        if (!children.hasProxy(child)) continue;

        return parent;
    }

    return QModelIndex();
}



int CampaignSkillProxyModel::rowCount(const QModelIndex &parent) const
{
    if (!parent.isValid())
    {
        return m_skills.count();
    }

    if (m_subSkills.contains(parent))
    {
        return m_subSkills.value(parent).proxies().count();
    }

    return 0;
}



int CampaignSkillProxyModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return (SkillData_LAST - SkillData_FIRST + 1);
}



QVariant CampaignSkillProxyModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid()) return QVariant();
    if (role != Qt::DisplayRole && role != Qt::EditRole) return QVariant();

    QModelIndex sourceIndex = mapToSource(index);
    if (!sourceIndex.isValid())
    {
        return "";
    }

    return sourceIndex.data(role);
}



QVariant CampaignSkillProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    Q_UNUSED(orientation);

    if (role != Qt::DisplayRole) return QVariant();

    switch (section)
    {
    case SkillName: return tr("Name");
    case SkillRef: return tr("Relations");
    }

    return QVariant();
}



QModelIndex CampaignSkillProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
{
    if (m_skills.hasSource(sourceIndex)) return m_skills.proxyOf(sourceIndex);

    QList<ProxyIndex> parents = m_subSkills.keys();
    foreach (ProxyIndex parent, parents)
    {
        if (!m_subSkills.value(parent).hasSource(sourceIndex)) continue;

        return m_subSkills.value(parent).proxyOf(sourceIndex);
    }

    return QModelIndex();
}



QModelIndex CampaignSkillProxyModel::mapToSource(const QModelIndex &proxyIndex) const
{
    if (m_skills.hasProxy(proxyIndex)) return m_skills.sourceOf(proxyIndex);


    QList<ProxyIndex> parents = m_subSkills.keys();
    foreach (ProxyIndex parent, parents)
    {
        if (!m_subSkills.value(parent).hasProxy(proxyIndex)) continue;

        return m_subSkills.value(parent).sourceOf(proxyIndex);
    }


    return QModelIndex();
}



void CampaignSkillProxyModel::remap()
{
    m_skills.clear();

    QAbstractItemModel* model = sourceModel();
    if (!model) return;


    for (int row = 0; row < model->rowCount(QModelIndex()); row++)
    {
        QModelIndex groupIndex = model->index(row, AbstractItem::IdData, QModelIndex());
        if (!groupIndex.isValid()) continue;

        if (!groupIndex.data(Qt::DisplayRole).toString().toLower().contains(SKILL_GROUP_NAME.toLower())) continue;

        mapItemIndexes(groupIndex);
    }

}



void CampaignSkillProxyModel::mapItemIndexes(const QModelIndex& groupIndex)
{
    QAbstractItemModel* model = sourceModel();
    if (!model) return;

    for (int row = 0; row < model->rowCount(groupIndex); row++)
    {
        QModelIndex itemIndex = model->index(row, AbstractItem::NameData, groupIndex);
        if (!itemIndex.isValid()) continue;

        m_skills.map(createIndex(itemIndex.row(), SkillName, itemIndex.internalPointer()), itemIndex);

        mapRefIndexes(itemIndex);
    }

}



void CampaignSkillProxyModel::mapRefIndexes(const QModelIndex& itemIndex)
{
    ItemModel* model = dynamic_cast<ItemModel*>(sourceModel());
    if (!model) return;

    for (int row = 0; row < model->rowCount(itemIndex); row++)
    {
        QModelIndex typeIndex = model->index(row, ItemReference::TypeData, itemIndex);
        QModelIndex refIndex = model->index(row, ItemReference::RefData, itemIndex);

        if (!typeIndex.isValid() || !refIndex.isValid()) continue;

        switch (typeIndex.data(Qt::EditRole).toInt())
        {
        case ItemReference::GroupRef:
            {
                mapSubSkills(refIndex);
                continue;
            }

        case ItemReference::BonusRef:
            {
                if (!refIndex.data(Qt::EditRole).toString().contains(ATTRIBUTE_GROUP_NAME)) continue;

                m_skills.map(createIndex(itemIndex.row(), SkillRef, refIndex.internalPointer()), refIndex);
                continue;
            }
        default:
            continue;
        }

    }

}



void CampaignSkillProxyModel::mapSubSkills(const QModelIndex &refIndex)
{
    if (!refIndex.isValid()) return;

    if (!refIndex.parent().isValid()) return;

    ProxyIndex parentProxy = m_skills.proxyOf(refIndex.parent());
    if (!parentProxy.isValid()) return;

    ItemModel* model = dynamic_cast<ItemModel*>(sourceModel());
    if (!model) return;


    QModelIndexList subSkills = model->references(refIndex);
    if (subSkills.isEmpty()) return;

    IndexMap sub_skills;
    foreach (QModelIndex subSkillIndex, subSkills)
    {
        if (!subSkillIndex.isValid()) return;

        QModelIndex nameSource = subSkillIndex.sibling(subSkillIndex.row(), AbstractItem::NameData);
        QModelIndex refSource = subSkillIndex.sibling(subSkillIndex.row(), AbstractItem::IdData);

        if (!nameSource.isValid() || !refSource.isValid()) continue;

        sub_skills.map(createIndex(subSkillIndex.row(), SkillName, nameSource.internalPointer()), nameSource);
        sub_skills.map(createIndex(subSkillIndex.row(), SkillRef, refSource.internalPointer()), refSource);

    }

    if (sub_skills.isEmpty()) return;

    m_subSkills.insert(parentProxy, sub_skills);

}



